#pragma once
#include<thread>
#include<mutex>
#include<condition_variable>
#include"../Channel/Channel.hpp"

class LoopThread{
private:
    EventLoop* _loop;//EvevtLoop的指针对象，需要在线程内实例化 
    std::thread _thread;
    //实现外界获取_loop的同步关系，避免外界获取时，_loop还没有初始化
    std::mutex _mutex;
    std::condition_variable _con;

    //实例化EventLoop对象，唤醒_cond阻塞的进程，并执行EventLoop的功能
    void thread_entry()
    {
        EventLoop loop;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _loop = &loop;
            _con.notify_all();
        }

        loop.Handle();
    }

public:
    //创建线程，设定线程的入口函数
    LoopThread()
    :_loop(nullptr)
    ,_thread(std::thread(&LoopThread::thread_entry, this))
    {}

    //获取_loop的接口
    EventLoop* GetLoop()
    {
        EventLoop* loop = nullptr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _con.wait(lock, [&]()->bool{return _loop != nullptr;});
            //直到_loop不为nullptr
            loop = _loop;
        }
        return loop;
    }
};

class LoopThreadPool{
private:
    int _thread_count;  //从属线程的数量
    int _next_thread;   //指向下一个将要被分配的线程
    EventLoop* _baseloop;   //用于连接监控的主线程
    std::vector<LoopThread*> _thread_pool;   //线程池
    std::vector<EventLoop*> _loops; //线程对应的事件监控和管理模块

public:
    LoopThreadPool(EventLoop* baseloop, int thread_count)
    :_baseloop(baseloop)
    ,_thread_count(thread_count)
    ,_next_thread(0)
    {
        InitPool();
    }

    LoopThreadPool(EventLoop* baseloop)
    :_baseloop(baseloop)
    ,_thread_count(0)
    ,_next_thread(0)
    {

    }

    void SetThreadCount(int count)
    {
        _thread_count = count;
    }

    void InitPool()
    {
        if(_thread_count > 0)
        {
            //空间初始化
            _thread_pool.resize(_thread_count);
            _loops.resize(_thread_count);

            for(int i = 0; i < _thread_count; i++)
            {
                _thread_pool[i] = new LoopThread();
                _loops[i] = _thread_pool[i]->GetLoop();
            }
        }
    }

    //返回下一个要使用的线程
    EventLoop* NextLoop()
    {
        //线程数量为0就直接返回主线程
        if(_thread_count == 0)
        {
            return _baseloop;
        }

        EventLoop* loop = _loops[_next_thread];
        _next_thread = (_next_thread+1)%_thread_count;
        return loop;
    }
};